package my.syncfilter.entity;

import com.alibaba.fastjson.annotation.JSONField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


public class MonitorData<T> implements DataChannel<T>
{

    private static Logger logger = LoggerFactory.getLogger(MonitorData.class);
    /**
     * 数据队列
     */
    @JSONField(serialize=false)
    private volatile ArrayBlockingQueue<T> dataQueue = null;

    private volatile int dbCounter;

    private volatile int cdrCounter;

    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date startDate;


    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private volatile Date dbLastTime;

    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private volatile Date cdrLastTime;

    //拉取文件速度
    private volatile long dbRate;

    //写文件速度
    private volatile long cdrRate;

    private volatile int queueSize;

    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date finishDate;

    // 运行状态：0-未启动 ；1-运行中； 3-完成；4-人工停止
    private int status;

    //0 等待执行，1 拉取数据 2 推送数据  3 拉取加推送
    private AtomicInteger wait;

    private int fileSize;

    private int uploadFileSize;

    /**
     * 加载数据完成
     */
    private volatile boolean loadFinished = false;

    private volatile int loadTotal;

    private volatile Object currentValue;

    /**
     * 存放汇总文件记录
     */
    @JSONField(serialize=false)
    private List<FileEntity> fileEntityList = Collections.synchronizedList(new ArrayList<FileEntity>());

    @JSONField(serialize=false)
    private Map<String, Integer> partitionMap = new ConcurrentHashMap<String, Integer>(8);

    public MonitorData()
    {
    }

    public MonitorData(int channelCapacity)
    {
        dataQueue=new ArrayBlockingQueue<T>(channelCapacity);
        startDate = new Date();
        dbLastTime = new Date();
        cdrLastTime = new Date();
        wait = new AtomicInteger(0);
    }

    public int calcQueueSize (){
        if(dataQueue!=null){
            queueSize = dataQueue.size();
        }
        return queueSize;
    }

    public long calcDbRate()
    {
        try
        {
            dbRate = (getDbCounter() / (dbLastTime.getTime() - startDate.getTime())) * 1000;
        }
        catch (Exception e)
        {
        }

        return dbRate;
    }

    public long calcCdrRate()
    {
        try
        {
            cdrRate = (getCdrCounter() / (cdrLastTime.getTime() - startDate.getTime())) * 1000;
        }
        catch (Exception e)
        {
        }
        return cdrRate;
    }

    public int calcFileSize() {
        int i=0;
        for (FileEntity fileEntity: fileEntityList) {
            if(fileEntity.getSumFile()!=null && fileEntity.getSumFile().getFileName()!=null){
                i++;
            }
        }
        fileSize=i;
        return fileSize;
    }

    public void addQueue(T data)
    {
        addQueue(data, null);
    }

    public void addQueue(T data, String partition)
    {
        //this.dataQueue.offer(data);
        try {
            dataQueue.put(data);
        }catch (Exception e){
            logger.error("队列存放异常",e);
        }

        cumulativeDbCounter();
        if (null!=partition)
        {
            Integer a = partitionMap.get(partition);
            if (a == null)
            {
                partitionMap.put(partition, 1);
            }
            else
            {
                partitionMap.put(partition, a + 1);
            }
        }
    }



    /**
     * 队列是否为空
     * @return
     */
    public boolean isQueueEmpty()
    {
        return dataQueue.isEmpty();
    }

    public T poll(long timeout)
    {
        T data = null;
        try {
            data = dataQueue.poll(timeout, TimeUnit.MILLISECONDS);
            if (data!=null)
            {
                cumulativeCdrCounter();
            }
            return data;
        }catch (Exception e){
            logger.error("获取数据异常",e);
        }
        return data;
    }


    public void cumulativeDbCounter()
    {
        dbLastTime = new Date();
        this.dbCounter++;
    }
    public void cumulativeCdrCounter()
    {
        cdrLastTime = new Date();
        this.cdrCounter++;
    }

    public void incrLoadTotal()
    {
        this.loadTotal++;
    }

    public void addFileEntityList(FileEntity fileEntity)
    {
        fileEntityList.add(fileEntity);
    }

    public int calcUploadFileSize()
    {
        int count = 0;
        for (FileEntity fileEntity:fileEntityList)
        {
            SumFile zip = fileEntity.getZip();
            //如果不上传zip 那么选择普通文件上传
            if (zip == null) {
                zip = fileEntity.getSumFile();
            }
            if (zip.isUpload())
            {
                count++;
            }
        }
        this.uploadFileSize = count;
        return this.uploadFileSize;
    }


    public int getDbCounter()
    {
        return dbCounter;
    }

    public int getCdrCounter()
    {
        return cdrCounter;
    }


    public boolean getLoadFinished()
    {
        return loadFinished;
    }

    public void setLoadFinished(boolean loadFinished)
    {
        this.loadFinished = loadFinished;
    }

    public Date getFinishDate()
    {
        return finishDate;
    }

    public void setFinishDate(Date finishDate)
    {
        this.finishDate = finishDate;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public int getStatus()
    {
        return status;
    }

    public void setStatus(int status)
    {
        this.status = status;
    }

    public int getLoadTotal()
    {
        return loadTotal;
    }

    public void setLoadTotal(int loadTotal)
    {
        this.loadTotal = loadTotal;
    }

    public Object getCurrentValue() {
        if (currentValue == null)
        {
            return 0;
        }
        return currentValue;
    }

    public void setCurrentValue(Object currentValue) {
        this.currentValue = currentValue;
    }

    public void setDbCounter(int dbCounter) {
        this.dbCounter = dbCounter;
    }

    public void setCdrCounter(int cdrCounter) {
        this.cdrCounter = cdrCounter;
    }

    public Date getDbLastTime() {
        return dbLastTime;
    }

    public void setDbLastTime(Date dbLastTime) {
        this.dbLastTime = dbLastTime;
    }

    public Date getCdrLastTime() {
        return cdrLastTime;
    }

    public void setCdrLastTime(Date cdrLastTime) {
        this.cdrLastTime = cdrLastTime;
    }

    public long getDbRate() {
        return dbRate;
    }

    public void setDbRate(long dbRate) {
        this.dbRate = dbRate;
    }

    public long getCdrRate() {
        return cdrRate;
    }

    public void setCdrRate(long cdrRate) {
        this.cdrRate = cdrRate;
    }

    public int getQueueSize() {
        return queueSize;
    }

    public void setQueueSize(int queueSize) {
        this.queueSize = queueSize;
    }

    public int getFileSize() {
        return fileSize;
    }

    public void setFileSize(int fileSize) {
        this.fileSize = fileSize;
    }

    public int getUploadFileSize() {
        return uploadFileSize;
    }

    public void setUploadFileSize(int uploadFileSize) {
        this.uploadFileSize = uploadFileSize;
    }

    public boolean isLoadFinished() {
        return loadFinished;
    }

    public List<FileEntity> getFileEntityList() {
        return fileEntityList;
    }

    public void setFileEntityList(List<FileEntity> fileEntityList) {
        this.fileEntityList = fileEntityList;
    }

    public Map<String, Integer> getPartitionMap() {
        return partitionMap;
    }

    public void setPartitionMap(Map<String, Integer> partitionMap) {
        this.partitionMap = partitionMap;
    }

    public AtomicInteger getWait() {
        return wait;
    }

    public void setWait(AtomicInteger wait) {
        this.wait = wait;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("MonitorData{");
        sb.append("dataQueue=").append(dataQueue);
        sb.append(", dbCounter=").append(dbCounter);
        sb.append(", cdrCounter=").append(cdrCounter);
        sb.append(", startDate=").append(startDate);
        sb.append(", dbLastTime=").append(dbLastTime);
        sb.append(", cdrLastTime=").append(cdrLastTime);
        sb.append(", dbRate=").append(dbRate);
        sb.append(", cdrRate=").append(cdrRate);
        sb.append(", queueSize=").append(queueSize);
        sb.append(", finishDate=").append(finishDate);
        sb.append(", status=").append(status);
        sb.append(", fileSize=").append(fileSize);
        sb.append(", uploadFileSize=").append(uploadFileSize);
        sb.append(", loadFinished=").append(loadFinished);
        sb.append(", loadTotal=").append(loadTotal);
        sb.append(", currentValue=").append(currentValue);
        sb.append(", fileEntityList=").append(fileEntityList);
        sb.append(", partitionMap=").append(partitionMap);
        sb.append('}');
        return sb.toString();
    }
}
